package com.yfp.operation.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson2.JSONObject;
import com.github.binarywang.wxpay.bean.entpay.EntPayRequest;
import com.github.binarywang.wxpay.bean.entpay.EntPayResult;
import com.github.binarywang.wxpay.bean.profitsharing.request.ProfitSharingUnfreezeV3Request;
import com.github.binarywang.wxpay.bean.profitsharing.request.ProfitSharingV3Request;
import com.github.binarywang.wxpay.bean.profitsharing.result.ProfitSharingUnfreezeV3Result;
import com.github.binarywang.wxpay.bean.profitsharing.result.ProfitSharingV3Result;
import com.github.binarywang.wxpay.bean.transfer.TransferBatchesRequest;
import com.github.binarywang.wxpay.bean.transfer.TransferBatchesResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.ProfitSharingService;
import com.github.binarywang.wxpay.service.WxPayService;
import com.hy.corecode.idgen.WFGIdGenerator;
import com.yfp.common.core.utils.ip.IpUtils;
import com.yfp.operation.config.WxPayConfiguration;
import com.yfp.operation.config.WxPayProperties;
import com.yfp.operation.domain.*;
import com.yfp.operation.enums.*;
import com.yfp.operation.enums.*;
import com.yfp.operation.mapper.UserWithdrawDetailMapper;
import com.yfp.operation.mapper.UserWithdrawMapper;
import com.yfp.operation.service.BillProfitSharingService;
import com.yfp.operation.service.OrderComboService;
import com.yfp.operation.service.OrderListService;
import com.yfp.operation.service.UserBillService;
import com.yfp.operation.domain.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description: 分账
 *
 * @CreateDate: 2024/6/21 10:02
 * @UpdateUser:
 * @UpdateDate: 2024/6/21 10:02
 * @UpdateRemark: 暂无修改
 * @Version: 1.0
 */
@Service
@Slf4j
public class BillProfitSharingServiceImpl implements BillProfitSharingService {
    @Resource
    private WxPayService wxPayService;
    @Autowired
    private UserWithdrawMapper userWithdrawMapper;
    @Autowired
    private UserWithdrawDetailMapper userWithdrawDetailMapper;
    @Autowired
    private UserBillService userBillService;
    @Autowired
    private WxPayProperties wxPayProperties;
    @Autowired
    private OrderListService orderListService;
    @Autowired
    private OrderComboService orderComboService;
    @Resource
    private WFGIdGenerator wFGIdGenerator;

    @Override
    @Async("threadPoolTaskExecutor")
    @Transactional
    public void profitSharing(Long userWithdrawId) throws WxPayException {
        UserWithdraw userWithdraw = userWithdrawMapper.getById(userWithdrawId);
        log.info("userWithdraw：{}", JSONObject.toJSONString(userWithdraw));
        List<UserWithdrawDetail> userWithdrawDetails = userWithdrawDetailMapper.getByUserWithdrawId(userWithdrawId);
        List<Long> userBillIds = userWithdrawDetails.stream().map(s -> s.getUserBillId()).collect(Collectors.toList());
        log.info("userBillIds：{}", JSONObject.toJSONString(userBillIds));
        if (CollUtil.isEmpty(userBillIds)){
            return;
        }
        List<UserBill> userBills = userBillService.getByIdsIn(userBillIds);
        Map<Long, UserBill> userBillMap = userBills.stream().collect(Collectors.toMap(UserBill::getId, userBill -> userBill));
        WxPayService mxPayService = WxPayConfiguration.getMxPayService(wxPayProperties.getConfigs().get(1));
        ProfitSharingService profitSharingService = mxPayService.getProfitSharingService();
        int index = 1;
        ProfitSharingV3Request profitSharingV3Request = null;
        TransferBatchesRequest transferBatchesRequest = null;
        TransferBatchesResult transferBatchesResult = null;
        ProfitSharingV3Result profitSharingV3Result = null;
        for (UserWithdrawDetail userWithdrawDetail : userWithdrawDetails) {

            index += 1;
            // 取模 30 =0，等待一秒 transaction_id
            if (index % 10 == 0) {
                try {
                    Thread.sleep(2000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            UserBill userBill = userBillMap.get(userWithdrawDetail.getUserBillId());
            userBill.setStatus(UserBillStatusEnums.WITHDRAWN.getStatus());
            userBillService.edit(userBill);
            try {
                // 金额为0，不进行分账
//                if (userBill.getMoney().compareTo(BigDecimal.valueOf(0)) != 1) {
//                    unfreeze(userBill.getId());
//                    continue;
//                }
                UserTypeEnums userTypeEnums = UserTypeEnums.getByType(userBill.getUserType());
                if (userBill.getPayType() == 2){
                    // 分账
                    profitSharingV3Request = new ProfitSharingV3Request();
                    List<ProfitSharingV3Request.Receiver> receivers = new ArrayList<>();
                    ProfitSharingV3Request.Receiver receiver = new ProfitSharingV3Request.Receiver();
                    receiver.setAccount(userBill.getReceiveAccount());
                    // 微信 分为单位
                    receiver.setAmount(userBill.getMoney().multiply(BigDecimal.valueOf(100)).intValue());
                    receiver.setType(userBill.getUserType() == UserTypeEnums.PERSON.getType() ? ReceiverTypeEnums.PERSONAL_OPENID.getType() : ReceiverTypeEnums.MERCHANT_ID.getType());
                    receiver.setDescription("分账给-" + userTypeEnums.getName() + "-" + userBill.getNickName());
                    receivers.add(receiver);

                    // 查询是否还有为提现的订单
                    List<UserBill> userBills1 = userBillService.getByOrderSnAndStatusNot(userBill.getOrderSn(), UserBillStatusEnums.WITHDRAWN.getStatus());
                    // 查询订单支付编号
                    List<OrderListDO> orderListDOS = orderListService.getByOrderSn(userBill.getOrderSn());
                    OrderComboDO orderComboDO = orderComboService.getOrderComboByOrderId(userBill.getOrderSn());

                    profitSharingV3Request.setReceivers(receivers);
                    profitSharingV3Request.setAppid(wxPayProperties.getConfigs().get(1).getAppId());
                    profitSharingV3Request.setOutOrderNo(userBill.getId() + "-" + userBill.getUserId());
                    // 解冻
                    profitSharingV3Request.setUnfreezeUnsplit(userBills1.size() == 1 ? true : false);
                    profitSharingV3Request.setTransactionId(orderListDOS.get(0).getPayTradeNo());
                    profitSharingV3Request.setSubMchId(orderComboDO.getMerchantId());
                    log.info("开始分账，profitSharingV3Request：{}", profitSharingV3Request);
                    Thread.sleep(500);
                    profitSharingV3Result = profitSharingService.profitSharingV3(profitSharingV3Request);
                    List<ProfitSharingV3Result.Receiver> resultReceivers = profitSharingV3Result.getReceivers();
                    log.info("分账响应为：{}", profitSharingV3Result);
                    if (resultReceivers.get(0).getResult().equals("PENDING")) {
                        userWithdrawDetail.setStatus(UserWithdrawDetailStatusEnums.PENDING.getStatus());
                    } else if (resultReceivers.get(0).getResult().equals("SUCCESS")) {
                        userWithdrawDetail.setStatus(UserWithdrawDetailStatusEnums.SUCCESS.getStatus());
                    } else if (resultReceivers.get(0).getResult().equals("CLOSED")) {
                        userWithdrawDetail.setStatus(UserWithdrawDetailStatusEnums.CLOSED.getStatus());
                    }
                    userWithdrawDetail.setOutOrderNo(profitSharingV3Request.getOutOrderNo());

                } else if(userBill.getPayType() == 3){
                    int money = userBill.getMoney().multiply(BigDecimal.valueOf(100)).intValue();
                    money = money >= 10 ? money : 10;
                    // 商家到账零钱
                    transferBatchesRequest = new TransferBatchesRequest();
                    transferBatchesRequest.setAppid(wxPayProperties.getConfigs().get(1).getAppId());
                    transferBatchesRequest.setOutBatchNo(String.valueOf(wFGIdGenerator.next()));
                    transferBatchesRequest.setBatchName("test");
                    transferBatchesRequest.setBatchRemark("分账提现");
                    transferBatchesRequest.setTotalAmount(money);
                    transferBatchesRequest.setTotalNum(1);

                    List<TransferBatchesRequest.TransferDetail> transferDetailList = new ArrayList<>();
                    TransferBatchesRequest.TransferDetail transferDetail = new TransferBatchesRequest.TransferDetail();
                    transferDetail.setOpenid(userBill.getReceiveAccount());
                    transferDetail.setOutDetailNo(String.valueOf(wFGIdGenerator.next()));
                    transferDetail.setTransferAmount(money);
                    transferDetail.setTransferRemark("分账给-" + userTypeEnums.getName() + "-" + userBill.getNickName());
                    if (money > 300){
                        transferDetail.setUserName(userBill.getNickName());
                    }
                    transferDetailList.add(transferDetail);
                    transferBatchesRequest.setTransferDetailList(transferDetailList);

                    transferBatchesResult = mxPayService.getTransferService().transferBatches(transferBatchesRequest);
                    if ( transferBatchesResult.getBatchStatus().equals("ACCEPTED")
                            || transferBatchesResult.getBatchStatus().equals("PROCESSING")
                            || transferBatchesResult.getBatchStatus().equals("FINISHED")) {
                        userWithdrawDetail.setStatus(UserWithdrawDetailStatusEnums.SUCCESS.getStatus());
                        // 处理转账成功逻辑
                    } else {
                        // 处理失败逻辑
                        userWithdrawDetail.setStatus(UserWithdrawDetailStatusEnums.CLOSED.getStatus());
                    }
                    userWithdrawDetail.setOutOrderNo(transferBatchesRequest.getOutBatchNo());
                }
            } catch (Exception e){
                log.error("分账异常：{}, userBill：{}", e , userBill);
                userWithdrawDetail.setStatus(UserWithdrawDetailStatusEnums.CLOSED.getStatus());
            }
            userWithdrawDetailMapper.editByBillId(userWithdrawDetail);
            userWithdraw.setStatus(UserWithdrawStatusEnums.COMPLETED.getStatus());
            userWithdraw.setRemitTime(new Date());
            userWithdrawMapper.edit(userWithdraw);
        }
    }

    @Override
    public void testEntPay() throws WxPayException {
        // 商家到账零钱
        WxPayService mxPayService =WxPayConfiguration.getMxPayService(wxPayProperties.getConfigs().get(1));
        TransferBatchesRequest transferBatchesRequest = new TransferBatchesRequest();
        transferBatchesRequest.setAppid(wxPayProperties.getConfigs().get(1).getAppId());
        transferBatchesRequest.setOutBatchNo("12345845115");
        transferBatchesRequest.setBatchName("test");
        transferBatchesRequest.setBatchRemark("分账提现");
        transferBatchesRequest.setTotalAmount(100);
        transferBatchesRequest.setTotalNum(1);

        List<TransferBatchesRequest.TransferDetail> transferDetailList = new ArrayList<>();
        TransferBatchesRequest.TransferDetail transferDetail = new TransferBatchesRequest.TransferDetail();
        transferDetail.setOpenid("oydmy64H2lWnVdyuZWj_NWMq40sw");
        transferDetail.setOutDetailNo("11231");
        transferDetail.setTransferAmount(100);
        transferDetail.setTransferRemark("分账提现");
        transferDetail.setUserName("苏治杰");
        transferDetailList.add(transferDetail);
        transferBatchesRequest.setTransferDetailList(transferDetailList);


        TransferBatchesResult transferBatchesResult = mxPayService.getTransferService().transferBatches(transferBatchesRequest);
        log.info("转账返回结果：{}", JSONObject.toJSONString(transferBatchesResult));
        if ( transferBatchesResult.getBatchStatus().equals("ACCEPTED") ||
                transferBatchesResult.getBatchStatus().equals("PROCESSING") || transferBatchesResult.getBatchStatus().equals("FINISHED")) {
            log.info("转账成功！");
            // 处理转账成功逻辑
        } else {
            // 处理失败逻辑
            log.info("转账失败！");
        }
    }

    @Override
    public void unfreeze(Long userBillId) {
        try {
            log.info("解冻全部剩余资金, userBillId: {}", userBillId);
            WxPayService mxPayService = WxPayConfiguration.getMxPayService(wxPayProperties.getConfigs().get(1));
            ProfitSharingService profitSharingService = mxPayService.getProfitSharingService();
            UserBill userBill = userBillService.findById(userBillId);
            List<OrderListDO> orderListDOS = orderListService.getByOrderSn(userBill.getOrderSn());
            OrderComboDO orderComboDO = orderComboService.getOrderComboByOrderId(userBill.getOrderSn());
            ProfitSharingUnfreezeV3Request request = new ProfitSharingUnfreezeV3Request();
            request.setDescription("解冻全部剩余资金");
            request.setOutOrderNo(userBill.getId() + "-" + userBill.getUserId());
            request.setSubMchId(orderComboDO.getMerchantId());
            request.setTransactionId(orderListDOS.get(0).getPayTradeNo());
            profitSharingService.profitSharingUnfreeze(request);
            userBill.setStatus(UserBillStatusEnums.CARRYTO.getStatus());
            userBillService.edit(userBill);
        } catch (Exception e){
            e.printStackTrace();
        }
    }


    @Override
    public void unfreeze(String payTradeNo) {
        WxPayService mxPayService = WxPayConfiguration.getMxPayService(wxPayProperties.getConfigs().get(1));
        ProfitSharingService profitSharingService = mxPayService.getProfitSharingService();
        ProfitSharingUnfreezeV3Request request = new ProfitSharingUnfreezeV3Request();
        request.setDescription("解冻全部剩余资金");
        request.setOutOrderNo(System.currentTimeMillis()+"");
        request.setSubMchId("1679326071");
        request.setTransactionId(payTradeNo);
        try {
            ProfitSharingUnfreezeV3Result profitSharingUnfreezeV3Result = profitSharingService.profitSharingUnfreeze(request);
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}
